package zhtt.example.filter;

import lombok.extern.slf4j.Slf4j;
import org.springframework.core.annotation.Order;
import org.springframework.core.io.buffer.DataBuffer;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.http.HttpStatus;
import org.springframework.http.MediaType;
import org.springframework.http.server.reactive.ServerHttpResponse;
import org.springframework.stereotype.Component;
import org.springframework.util.MultiValueMap;
import org.springframework.web.server.ServerWebExchange;
import org.springframework.web.server.WebFilter;
import org.springframework.web.server.WebFilterChain;
import org.springframework.web.server.WebSession;
import reactor.core.publisher.Mono;

import java.util.List;
import java.util.Set;

/**
 * Created by zhaoq on   2024/7/23 16:26
 **/
//@Component
@Order(1)
@Slf4j
public class LoginUserSessionWebFilter implements WebFilter {

    private final String SK_NONCE_KEY="SK_NONCE_KEY";
    private final String SK_LOGIN_USER_KEY="SK_LOGIN_USER_KEY";

    @Override
    public Mono<Void> filter(ServerWebExchange exchange, WebFilterChain chain) {
        return exchange.getSession()
                .doOnNext(session -> {
                    String userInfo = session.getAttribute(SK_LOGIN_USER_KEY);
                    if(userInfo==null){
                        session.getAttributes().put(SK_LOGIN_USER_KEY,"userInfo");
                        session.save();
                    }else{
                        System.out.println(userInfo);
                    }
                })
                .then(chain.filter(exchange));
    }

    private void cacheLoginUser(ServerWebExchange exchange, WebSession session){
        String path = exchange.getRequest().getPath().value();
    }

    private void checkPostData(ServerWebExchange exchange){
        String method = exchange.getRequest().getMethod().name();
        System.out.println(method);
    }


    public Mono<Void> redirectHandler(ServerWebExchange exchange) {
        exchange.getSession().block().invalidate();
        String Token = getHeader(exchange, "authToken");
        if("authToken".equals(Token)){
            ServerHttpResponse response = exchange.getResponse();
            // 设置响应头，‌例如内容类型
            response.getHeaders().setContentType(MediaType.APPLICATION_JSON);
            String data = "{code: 200}";
            DataBuffer buffer = response.bufferFactory().wrap(data.getBytes());
            // 写入响应体并返回
            return response.writeWith(Mono.just(buffer));

        }else{
            // 重定向到其他地址
            exchange.getResponse().setStatusCode(HttpStatus.TEMPORARY_REDIRECT);
            String referer = getHeader(exchange, "referer");
            exchange.getResponse().getHeaders().set("Location", referer);
            return exchange.getResponse().setComplete();
        }
    }


    public String getHeader(ServerWebExchange exchange, String key) {
        List<String> valueList = exchange.getRequest().getHeaders().get(key);
        if (valueList == null) {
            return null;
        }
        String value = valueList.get(0);
        return value;

    }

    private String getParam(ServerWebExchange exchange, String key) {
        List<String> valueList = exchange.getRequest().getQueryParams().get(key);
        if (valueList == null) {
            return null;
        }
        String value = valueList.get(0);
        return value;
    }

    private String getParams(ServerWebExchange exchange){
        MultiValueMap<String, String> paramsMap = exchange.getRequest().getQueryParams();
        if(paramsMap==null||paramsMap.isEmpty()){
            String requestURI = exchange.getRequest().getPath().value();
            //log.info("params is null: "+requestURI);
            return "";
        }
        Set<String> paramsSet = paramsMap.keySet();
        StringBuffer buffer = new StringBuffer();
        for(String paramKey: paramsSet){
            List<String> valueList = paramsMap.get(paramKey);
            buffer.append(paramKey+"="+String.join(", ", valueList).toString()+"&");
        }
        return buffer.substring(0, buffer.length()-1).toString();
    }

    private String getSessionId(ServerWebExchange exchange) {
        return exchange.getSession().block().getId();
    }


    private String getIpAddress(ServerWebExchange exchange) {
        Mono<String> mono = Mono.just(exchange.getRequest().getRemoteAddress().getAddress().getHostAddress());
        String ip = mono.block().toString();
        return ip;
    }


    private String getOsAndBrowserInfo(ServerWebExchange exchange) {
        String agent = getHeader(exchange, "user-agent");
        return agent;
    }


    public boolean isReplayAttack(ServerWebExchange exchange, RedisTemplate redisTemplate) {
        String signId = getParam(exchange, "signId");
        if(null== signId || signId.length()<30){
            return true;
        }
        boolean nonceExists = redisTemplate.hasKey(SK_NONCE_KEY + signId);
        if (nonceExists) {
            //log.info(exchange.getRequest().getMethod() + " - " + signId + " - 请求重复isReplayAttack！");
            return true;
        } else {
            long now = System.currentTimeMillis();
            redisTemplate.opsForSet().add(SK_NONCE_KEY + signId, signId, 14400L);
            String timeStr = signId.substring(10, 21);
            long time = Long.parseLong(timeStr, 16);
            //log.info("isReplayAttack--请求耗时：" + ((now - time) / 1000));
            return false;
        }
    }
}
